import logging
from logging.handlers import RotatingFileHandler
from concurrent_log_handler import ConcurrentRotatingFileHandler
import os
from typing import Dict

# 用于单例模式的缓存
_loggers: Dict[str, logging.Logger] = {}


class LogManager:
    @staticmethod
    def get_console_logger(
            name='console_logger',
            log_level=logging.INFO,
            log_format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    ):
        """
        获取仅控制台输出的日志记录器

        :param name: 日志记录器名称
        :param log_level: 日志级别
        :param log_format: 日志格式
        :return: 配置好的日志记录器实例
        """
        return LogManager._setup_logger(
            name=name,
            log_level=log_level,
            log_format=log_format,
            output_mode='console'
        )

    @staticmethod
    def get_file_logger(
            name='file_logger',
            log_level=logging.INFO,
            log_format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            log_file='app.log',
            max_bytes=10 * 1024 * 1024,
            backup_count=5,
            use_multiprocess=False
    ):
        """
        获取仅文件输出的日志记录器

        :param name: 日志记录器名称
        :param log_level: 日志级别
        :param log_format: 日志格式
        :param log_file: 日志文件路径
        :param max_bytes: 单个日志文件最大大小
        :param backup_count: 日志文件备份数量
        :param use_multiprocess: 是否用于多进程环境
        :return: 配置好的日志记录器实例
        """
        return LogManager._setup_logger(
            name=name,
            log_level=log_level,
            log_format=log_format,
            output_mode='file',
            log_file=log_file,
            max_bytes=max_bytes,
            backup_count=backup_count,
            use_multiprocess=use_multiprocess
        )

    @staticmethod
    def get_both_logger(
            name='both_logger',
            log_level=logging.INFO,
            log_format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            log_file='app.log',
            max_bytes=10 * 1024 * 1024,
            backup_count=5,
            use_multiprocess=False
    ):
        """
        获取控制台和文件同时输出的日志记录器

        :param name: 日志记录器名称
        :param log_level: 日志级别
        :param log_format: 日志格式
        :param log_file: 日志文件路径
        :param max_bytes: 单个日志文件最大大小
        :param backup_count: 日志文件备份数量
        :param use_multiprocess: 是否用于多进程环境
        :return: 配置好的日志记录器实例
        """
        return LogManager._setup_logger(
            name=name,
            log_level=log_level,
            log_format=log_format,
            output_mode='both',
            log_file=log_file,
            max_bytes=max_bytes,
            backup_count=backup_count,
            use_multiprocess=use_multiprocess
        )

    @staticmethod
    def _setup_logger(
            name,
            log_level,
            log_format,
            output_mode,
            log_file='app.log',
            max_bytes=10 * 1024 * 1024,
            backup_count=5,
            use_multiprocess=False
    ):
        """
        内部方法：配置日志记录器
        """
        global _loggers

        if name in _loggers:
            return _loggers[name]

        logger = logging.getLogger(name)
        logger.setLevel(log_level)
        logger.handlers.clear()

        formatter = logging.Formatter(log_format)

        if output_mode in ('console', 'both'):
            console_handler = logging.StreamHandler()
            console_handler.setFormatter(formatter)
            logger.addHandler(console_handler)

        if output_mode in ('file', 'both'):
            log_dir = os.path.dirname(log_file) or '.'
            os.makedirs(log_dir, exist_ok=True)

            if use_multiprocess:
                file_handler = ConcurrentRotatingFileHandler(
                    log_file,
                    maxBytes=max_bytes,
                    backupCount=backup_count,
                    encoding='utf-8'
                )
            else:
                file_handler = RotatingFileHandler(
                    log_file,
                    maxBytes=max_bytes,
                    backupCount=backup_count
                )
            file_handler.setFormatter(formatter)
            logger.addHandler(file_handler)

        _loggers[name] = logger
        return logger


if __name__ == '__main__':
    # 示例用法
    pass
    # 仅控制台输出
    console_logger = LogManager.get_console_logger(name='example_console')
    console_logger.info('这是一条仅在控制台输出的日志')

    # 仅文件输出
    file_logger = LogManager.get_file_logger(
        name='example_file',
        log_file='examples/file_example.log'
    )
    file_logger.info('这是一条仅在文件中输出的日志')

    # 控制台和文件同时输出
    both_logger = LogManager.get_both_logger(
        name='example_both',
        log_file='examples/both_example.log'
    )
    both_logger.info('这是一条同时在控制台和文件中输出的日志')
